package controllers

import (
	"beego/comm/auth"
	"beego/comm/str"
	"beego/comm/utils"
	"fmt"
	"strconv"
	"strings"
	"sync"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

var (
	lockAddRole sync.Mutex
)

type RoleController struct {
	beego.Controller
}

func (c *RoleController) QueryRole() {
	beego.Info("================= QueryRole start =================")
	result := map[string]interface{}{
		"role":  []string{},
		"error": "",
	}
	c.Data["json"] = result
	defer func() {
		err := recover()
		if nil != err {
			result["error"] = err
			c.ServeJSON()
		}
	}()
	auth.HandleLogin(c.Ctx.Input.RequestBody)
	var maps []orm.Params
	sql := "select distinct role from page_role"
	beego.Info(sql)
	o := orm.NewOrm()
	o.Raw(sql).Values(&maps)
	for id, value := range maps {
		value["id"] = fmt.Sprintf("%d", id)
	}
	result["role"] = maps
	c.ServeJSON()
	beego.Info("================= QueryRole end =================")
}

func (c *RoleController) QueryPageList() {
	beego.Info("================= QueryPageList start =================")
	result := map[string]interface{}{
		"page_dir": []interface{}{},
		"error":    "",
	}
	c.Data["json"] = result
	defer func() {
		err := recover()
		if nil != err {
			result["error"] = err
			c.ServeJSON()
		}
	}()
	auth.HandleLogin(c.Ctx.Input.RequestBody)
	var maps []orm.Params
	o := orm.NewOrm()
	sql := "select page_id id, page_path, page_name, parent_page_id from page_dir where parent_page_id <> '0' order by modify_time"
	beego.Info(sql)
	o.Raw(sql).Values(&maps)
	prefix_dir := map[string]string{}
	for _, value := range maps {
		v, ok := prefix_dir[value["parent_page_id"].(string)]
		page_name := value["page_name"].(string)
		if ok {
			value["abs_path"] = v + "/" + page_name
		} else {
			value["abs_path"] = page_name
		}
		prefix_dir[value["id"].(string)] = page_name
	}
	result["page_dir"] = maps
	c.Data["json"] = result
	c.ServeJSON()
	beego.Info("================= QueryPageList end =================")
}

func (c *RoleController) AddRole() {
	beego.Info("================= AddRole start =================")
	result := map[string]interface{}{
		"status": true,
		"error":  "",
	}
	c.Data["json"] = result
	defer func() {
		err := recover()
		if nil != err {
			result["status"] = false
			result["error"] = err
			c.ServeJSON()
		}
	}()
	resmap := auth.HandleLogin(c.Ctx.Input.RequestBody)
	role_name := utils.CheckFieldExists(resmap, "role").(string)
	if strings.Trim(role_name, " ") == "" {
		panic("角色名为空")
	}
	page_list := utils.CheckFieldExists(resmap, "page_list").([]interface{})
	if len(page_list) == 0 {
		panic("page_list为空")
	}
	save_role_map(role_name, page_list)
	c.ServeJSON()
	beego.Info("================= AddRole end =================")
}

func (c *RoleController) UpdateRole() {
	beego.Info("================= UpdateRole start =================")
	result := map[string]interface{}{
		"status": true,
		"error":  "",
	}
	c.Data["json"] = result
	defer func() {
		err := recover()
		if nil != err {
			result["status"] = false
			result["error"] = err
			c.ServeJSON()
		}
	}()
	resmap := auth.HandleLogin(c.Ctx.Input.RequestBody)
	role_name := utils.CheckFieldExists(resmap, "role").(string)
	if strings.Trim(role_name, " ") == "" {
		panic("角色名为空")
	}
	page_list := utils.CheckFieldExists(resmap, "page_list").([]interface{})
	if len(page_list) == 0 {
		panic("page_list为空")
	}
	o := orm.NewOrm()
	var maps []orm.Params
	sql := fmt.Sprintf("select page_path from page_role where role='%s'", role_name)
	beego.Info(sql)
	o.Raw(sql).Values(&maps)
	add_page_path := []interface{}{}
	del_page_path := []string{}
	db_page_path := []interface{}{}
	for _, value := range maps {
		db_page_path = append(db_page_path, value["page_path"])
		if !utils.In(page_list, value["page_path"]) {
			del_page_path = append(del_page_path, value["page_path"].(string))
		}
	}
	for _, value := range page_list {
		if !utils.In(db_page_path, value) {
			add_page_path = append(add_page_path, value)
		}
	}
	save_role_map(role_name, add_page_path)
	where := "('" + strings.Join(del_page_path, "', '") + "')"
	sql = fmt.Sprintf("delete from page_role where role='%s' and page_path in %s", role_name, where)
	beego.Info(sql)
	exe_result, err := o.Raw(sql).Exec()
	beego.Info(fmt.Sprintf("delete执行结果: %s", exe_result))
	beego.Info(fmt.Sprintf("执行状态: %s", err))
	c.ServeJSON()
	beego.Info("================= UpdateRole end =================")
}

func save_role_map(role_name string, page_list []interface{}) {
	lockAddRole.Lock()
	o := orm.NewOrm()
	var maps []orm.Params
	sql := `select cur_id from sequence where table_name = 'page_role'`
	beego.Info(sql)
	o.Raw(sql).Values(&maps)
	cur_id, _ := strconv.ParseInt(maps[0]["cur_id"].(string), 10, 64)
	var role_items = map[string]interface{}{
		"sql": make([]string, 0),
		"len": 0,
	}
	for _, page := range page_list {
		cur_id_tmp := fmt.Sprintf("%d", cur_id)
		var food_item = map[string]interface{}{
			"role_id":   cur_id_tmp,
			"role":      role_name,
			"page_path": page.(string),
		}
		role_items = str.GenInsertSql(role_items, food_item, "page_role")
		cur_id += 1
	}
	data_sql, _ := role_items["sql"].([]string)
	for _, food_item_v := range data_sql {
		beego.Info(food_item_v)
		exe_result, err := o.Raw(food_item_v).Exec()
		beego.Info(fmt.Sprintf("insert执行结果: %s", exe_result))
		beego.Info(fmt.Sprintf("执行状态: %s", err))
	}
	cur_id_d := fmt.Sprintf("%d", cur_id)
	sql = `update sequence set cur_id = "` + cur_id_d + `" where table_name = 'page_role'`
	beego.Info(sql)
	exe_result, err := o.Raw(sql).Exec()
	beego.Info(fmt.Sprintf("update执行结果: %s", exe_result))
	beego.Info(fmt.Sprintf("执行状态: %s", err))
	lockAddRole.Unlock()
}

func (c *RoleController) QueryRoleDetail() {
	beego.Info("================= QueryRoleDetail start =================")
	result := map[string]interface{}{
		"page_path": []string{},
		"error":     "",
	}
	c.Data["json"] = result
	defer func() {
		err := recover()
		if nil != err {
			result["error"] = err
			c.ServeJSON()
		}
	}()
	resmap := auth.HandleLogin(c.Ctx.Input.RequestBody)
	role_name := utils.CheckFieldExists(resmap, "role").(string)
	if strings.Trim(role_name, " ") == "" {
		panic("角色名为空")
	}
	var maps []orm.Params
	sql := fmt.Sprintf("select page_path from page_role where role='%s'", role_name)
	beego.Info(sql)
	o := orm.NewOrm()
	o.Raw(sql).Values(&maps)
	page_path := []string{}
	for _, value := range maps {
		page_path = append(page_path, value["page_path"].(string))
	}
	result["page_path"] = page_path
	c.Data["json"] = result
	c.ServeJSON()
	beego.Info("================= QueryRoleDetail end =================")
}

func (c *RoleController) DelRole() {
	beego.Info("================= DelRole start =================")
	result := map[string]interface{}{
		"status": false,
		"error":  "",
	}
	c.Data["json"] = result
	defer func() {
		err := recover()
		if nil != err {
			result["error"] = err
			c.ServeJSON()
		}
	}()
	resmap := auth.HandleLogin(c.Ctx.Input.RequestBody)
	role_list_i := utils.CheckFieldExists(resmap, "role_list").([]interface{})
	if len(role_list_i) == 0 {
		panic("角色为空")
	}
	role_list := []string{}
	for _, value := range role_list_i {
		role_list = append(role_list, value.(string))
	}
	where := "('" + strings.Join(role_list, "', '") + "')"
	sql := fmt.Sprintf("delete from page_role where role in %s", where)
	beego.Info(sql)
	o := orm.NewOrm()
	exe_result, err := o.Raw(sql).Exec()
	beego.Info(fmt.Sprintf("delete执行结果: %s", exe_result))
	beego.Info(fmt.Sprintf("执行状态: %s", err))
	result["status"] = true
	c.Data["json"] = result
	c.ServeJSON()
	beego.Info("================= DelRole end =================")
}
